/*
 * streamerDemo.cpp
 *
 *  Created on: Sep 23, 2012
 *      Author: shaohong
 */


#include <iostream>
#include <fstream>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include <pthread.h>
#include "RtpStreamer.h"


using namespace std;
using namespace nmps;

//static AppLogger * logger = AppLogger::getInstance("StreamerDemo");

static const char *optString = "+t:f:h?";

struct Config{
	string receiverIP;
	int receiverPort;
	string audioFile;
};

static void printUsage() {
	cerr<< "streamerDemo -f pcmFile -t targetIP:port" << endl;
}


void parseCommandLine(int argc, char *argv[], struct Config& streamerConfig) {

	streamerConfig.audioFile = "";
	streamerConfig.receiverPort = 0;

	int opt = getopt(argc, argv, optString);
	while (opt != -1) {

		switch (opt) {
		case 'f':
			if (NULL != optarg) {
				streamerConfig.audioFile = optarg;
			} else {
				printUsage();
				exit(EXIT_FAILURE);
			}
			break;

		case 't':
			if (NULL != optarg) {
				//argument following -t option gives the RTP receiver address
				string targetAddress = string(optarg);
				size_t seperatorPos = targetAddress.find(':', 0);

				if (seperatorPos == string::npos) {
					fprintf(stderr, "invalid -c option: %s", optarg);
					printUsage();
					exit(EXIT_FAILURE);
				} else {
					streamerConfig.receiverIP =targetAddress.substr(0, seperatorPos);;
					string portStr = targetAddress.substr(seperatorPos+1);
					streamerConfig.receiverPort = atoi(portStr.c_str());

				}
			}
			break;

		case 'h':
		case '?':
			printUsage();
			exit(EXIT_FAILURE);
			break;

		default:
			printUsage();

			exit(EXIT_FAILURE);
		}

		opt = getopt(argc, argv, optString);
	}

	//check if the command line arguments are valid
	if (streamerConfig.audioFile == "" || streamerConfig.receiverPort == 0) {
		printUsage();

		exit(EXIT_FAILURE);
	}


}


/**
 * RTP Sending thread.
 * It starts a timer and every 20ms, it will get 160 bytes from the “AudioPlayoutBuffer”
 * and send the audio data to remote client via RTP.
 */
static void * startRTPStreaming(void *arg) {

	cout << "RTPStreaming Thread started!" << endl;
	RtpStreamer * rtpStreamer = static_cast<RtpStreamer *>(arg);

	const long MILLION = 100000L;

	struct timeval tBefore, tAfter;
	long timedif;

	struct timeval tv;
	tv.tv_sec = 0;
	tv.tv_usec = 20 * 1000; //20 ms

	while (0 != rtpStreamer->getPlayoutBuffer()->getNumberOfBlocks()) {

		select(0, NULL, NULL, NULL, &tv);

		gettimeofday(&tBefore, NULL);

		rtpStreamer->sendDataOverRTP(false);

		gettimeofday(&tAfter, NULL);

		//adjust for the time spent sending the packet
		timedif = (tAfter.tv_sec - tBefore.tv_sec) * MILLION + (tAfter.tv_usec - tBefore.tv_usec);
		tv.tv_sec = 0;
		tv.tv_usec = 20 * 1000 - timedif;
		if (tv.tv_usec <=0){
			fprintf(stderr, "-");
			tv.tv_usec = 0;
		}

	}

	return 0;
}

int main(int argc, char ** argv) {

	//parse and check command line arguments
	struct Config config;
	parseCommandLine(argc, argv, config);

	cout <<"receiver = "<< config.receiverIP << ":" << config.receiverPort << endl;
	cout <<"audio file = " << config.audioFile << endl;

	//create a rtpStreamer and fill its buffer with the audio payload
	RtpStreamer * rtpStreamer = new RtpStreamer();
	rtpStreamer->initialize();
	rtpStreamer->addRecipient(config.receiverIP, config.receiverPort);

    fstream audioFile(config.audioFile.c_str(),ios::binary|ios::in);

    // skip the header bytes
    audioFile.seekg(44, ios::beg);
    char audioContent[1024];
	//fill the buffers with the audio file content
	PcmPlayoutBuffer *playoutBuffer = rtpStreamer->getPlayoutBuffer();

    while (!audioFile.eof()) {
    	audioFile.read(audioContent, sizeof(audioContent));

    	playoutBuffer->enQueuePcmDataBlock((int)audioFile.gcount(), (unsigned char *)audioContent);

    }
    audioFile.close();

    cout << "playoutBuffer->getTotalPCMDataSize()=" << playoutBuffer->getTotalPCMDataSize() << endl;

	pthread_t rtpStreamingThread;

	// fire off the RTP streaming thread
	pthread_create(&rtpStreamingThread, NULL, startRTPStreaming, rtpStreamer);

	pthread_join(rtpStreamingThread, NULL);

	delete rtpStreamer;
}


